import { PrismaClient } from '@prisma/client';
import { createModuleLogger } from '../../utils/logger';
import { ChainType, Transaction, AddressLabel, AlertMessage } from '../../types';

const logger = createModuleLogger('prisma-service');

export class PrismaService {
  private prisma: PrismaClient;
  private transactionRetryQueue: Map<string, { transaction: Transaction; retryCount: number }> = new Map();
  private maxRetries = 3;
  private retryDelay = 1000; // 1秒

  constructor() {
    this.prisma = new PrismaClient({
      log: [
        {
          emit: 'event',
          level: 'query',
        },
        {
          emit: 'event',
          level: 'error',
        },
        {
          emit: 'event',
          level: 'info',
        },
        {
          emit: 'event',
          level: 'warn',
        },
      ],
    });

    // Log database queries in development
    if (process.env.NODE_ENV === 'development') {
      this.prisma.$on('query', (e) => {
        logger.debug('Query:', e.query);
        logger.debug('Duration:', `${e.duration}ms`);
      });
    }

    this.prisma.$on('error', (e) => {
      logger.error('Database error:', e);
    });
  }

  // Initialize database connection
  public async connect(): Promise<void> {
    try {
      await this.prisma.$connect();
      logger.info('Database connected successfully');
    } catch (error) {
      logger.error('Failed to connect to database:', error);
      throw error;
    }
  }

  // Disconnect from database
  public async disconnect(): Promise<void> {
    try {
      await this.prisma.$disconnect();
      logger.info('Database disconnected');
    } catch (error) {
      logger.error('Error disconnecting from database:', error);
    }
  }

  // ===== Transaction Operations =====

  public async saveTransaction(transaction: Transaction): Promise<void> {
    try {
      await this.saveTransactionWithRetry(transaction);
    } catch (error) {
      logger.error('Failed to save transaction after all retries:', error);
      // 降级到内存存储
      await this.saveTransactionToFallbackStorage(transaction);
    }
  }

  private async saveTransactionWithRetry(transaction: Transaction, currentRetry: number = 0): Promise<void> {
    try {
      // 数据验证和清理
      if (!transaction.hash || !transaction.chain) {
        logger.warn('Skipping transaction with missing hash or chain');
        return;
      }

      // 验证地址不为空
      if (!transaction.fromAddress || !transaction.toAddress) {
        logger.warn(`Skipping transaction ${transaction.hash} with empty addresses`);
        return;
      }

      // 验证和转换 valueUsd
      const valueUsd = Number(transaction.valueUsd);
      if (isNaN(valueUsd) || valueUsd < 0) {
        logger.warn(`Skipping transaction ${transaction.hash} with invalid valueUsd: ${transaction.valueUsd}`);
        return;
      }

      // 数据类型转换和验证
      const timestamp = transaction.timestamp instanceof Date 
        ? transaction.timestamp 
        : new Date(transaction.timestamp);

      const transactionData = {
          hash: transaction.hash,
          chain: transaction.chain,
        fromAddress: transaction.chain === 'bitcoin' ? transaction.fromAddress : transaction.fromAddress.toLowerCase(),
        toAddress: transaction.chain === 'bitcoin' ? transaction.toAddress : transaction.toAddress.toLowerCase(),
        value: transaction.value.toString(), // 确保为字符串
        valueUsd: valueUsd,
          tokenAddress: transaction.tokenAddress && transaction.chain !== 'bitcoin' ? transaction.tokenAddress.toLowerCase() : transaction.tokenAddress || null,
          tokenSymbol: transaction.tokenSymbol || null,
          tokenDecimals: transaction.tokenDecimals ? Number(transaction.tokenDecimals) : null,
          blockNumber: BigInt(transaction.blockNumber),
          blockHash: transaction.blockHash || null,
          transactionIndex: transaction.transactionIndex || null,
          gasUsed: transaction.gasUsed ? BigInt(transaction.gasUsed) : null,
          gasPrice: transaction.gasPrice ? BigInt(transaction.gasPrice) : null,
          timestamp: timestamp,
          confirmed: transaction.confirmed !== undefined ? transaction.confirmed : true,
          fromLabel: transaction.fromLabel || null,
          toLabel: transaction.toLabel || null,
      };

      await this.prisma.transaction.upsert({
        where: { hash: transaction.hash },
        update: {
          valueUsd: valueUsd,
          fromLabel: transactionData.fromLabel,
          toLabel: transactionData.toLabel,
          gasUsed: transactionData.gasUsed,
          gasPrice: transactionData.gasPrice,
        },
        create: transactionData,
      });
      
      logger.debug(`Transaction saved: ${transaction.hash} on ${transaction.chain}`);
      
      // 如果之前有重试记录，清除它
      this.transactionRetryQueue.delete(transaction.hash);
      
    } catch (error) {
      logger.error(`Failed to save transaction (attempt ${currentRetry + 1}/${this.maxRetries}):`, error);
      
      if (currentRetry < this.maxRetries - 1) {
        // 重试
        const delay = this.retryDelay * Math.pow(2, currentRetry); // 指数退避
        logger.info(`Retrying transaction ${transaction.hash} in ${delay}ms...`);
        
        setTimeout(async () => {
          try {
            await this.saveTransactionWithRetry(transaction, currentRetry + 1);
          } catch (retryError) {
            logger.error(`Retry failed for transaction ${transaction.hash}:`, retryError);
          }
        }, delay);
      } else {
        // 所有重试都失败，抛出错误
        throw error;
      }
    }
  }

  private async saveTransactionToFallbackStorage(transaction: Transaction): Promise<void> {
    try {
      // 简单的内存存储作为降级方案
      const fallbackKey = `fallback_${transaction.hash}`;
      this.transactionRetryQueue.set(fallbackKey, {
        transaction,
        retryCount: this.maxRetries
      });
      
      logger.warn(`Transaction ${transaction.hash} saved to fallback storage`);
      
      // 可以在这里添加其他降级存储方案，比如写入文件
      // await this.writeToFile(transaction);
      
    } catch (error) {
      logger.error('Failed to save to fallback storage:', error);
    }
  }

  // 定期重试降级存储的交易
  public async retryFallbackTransactions(): Promise<void> {
    if (this.transactionRetryQueue.size === 0) return;
    
    logger.info(`Retrying ${this.transactionRetryQueue.size} fallback transactions...`);
    
    const fallbackEntries = Array.from(this.transactionRetryQueue.entries());
    for (const [key, { transaction }] of fallbackEntries) {
      try {
        await this.saveTransactionWithRetry(transaction);
        this.transactionRetryQueue.delete(key);
        logger.info(`Successfully saved fallback transaction: ${transaction.hash}`);
      } catch (error) {
        logger.error(`Still failed to save fallback transaction ${transaction.hash}:`, error);
      }
    }
  }

  public async getTransactionById(id: string): Promise<any | null> {
    try {
      const transaction = await this.prisma.transaction.findFirst({
        where: {
          OR: [
            { id: parseInt(id) },
            { hash: id }
          ]
        }
      });

      if (!transaction) return null;

      return {
        id: transaction.id.toString(),
        hash: transaction.hash,
        chain: transaction.chain as ChainType,
        fromAddress: transaction.fromAddress,
        toAddress: transaction.toAddress,
        value: parseFloat(transaction.value.toString()),
        valueUsd: parseFloat(transaction.valueUsd.toString()),
        tokenAddress: transaction.tokenAddress,
        tokenSymbol: transaction.tokenSymbol,
        tokenDecimals: transaction.tokenDecimals,
        blockNumber: transaction.blockNumber.toString(),
        timestamp: transaction.timestamp,
        fromLabel: transaction.fromLabel,
        toLabel: transaction.toLabel
      };
    } catch (error) {
      logger.error('Failed to get transaction by ID:', error);
      throw error;
    }
  }

  public async getTransactionsByAddress(address: string, chain: ChainType): Promise<any[]> {
    try {
      const transactions = await this.prisma.transaction.findMany({
        where: {
          AND: [
            {
              OR: [
                { fromAddress: address.toLowerCase() },
                { toAddress: address.toLowerCase() }
              ]
            },
            { chain }
          ]
        },
        orderBy: { timestamp: 'desc' },
        take: 100
      });

      return transactions.map(tx => ({
        id: tx.id.toString(),
        hash: tx.hash,
        chain: tx.chain,
        fromAddress: tx.fromAddress,
        toAddress: tx.toAddress,
        value: parseFloat(tx.value.toString()),
        valueUsd: parseFloat(tx.valueUsd.toString()),
        tokenAddress: tx.tokenAddress,
        tokenSymbol: tx.tokenSymbol,
        tokenDecimals: tx.tokenDecimals,
        blockNumber: tx.blockNumber.toString(),
        timestamp: tx.timestamp,
        fromLabel: tx.fromLabel,
        toLabel: tx.toLabel
      }));
    } catch (error) {
      logger.error('Failed to get transactions by address:', error);
      throw error;
    }
  }

  public async getRecentTransactionsByAddress(address: string, chain: ChainType, hours: number): Promise<any[]> {
    try {
      const hoursAgo = new Date(Date.now() - hours * 60 * 60 * 1000);
      
      const transactions = await this.prisma.transaction.findMany({
        where: {
          AND: [
            {
              OR: [
                { fromAddress: address.toLowerCase() },
                { toAddress: address.toLowerCase() }
              ]
            },
            { chain },
            { timestamp: { gte: hoursAgo } }
          ]
        },
        orderBy: { timestamp: 'desc' }
      });

      return transactions.map(tx => ({
        id: tx.id.toString(),
        hash: tx.hash,
        chain: tx.chain,
        fromAddress: tx.fromAddress,
        toAddress: tx.toAddress,
        value: parseFloat(tx.value.toString()),
        valueUsd: parseFloat(tx.valueUsd.toString()),
        tokenAddress: tx.tokenAddress,
        tokenSymbol: tx.tokenSymbol,
        tokenDecimals: tx.tokenDecimals,
        blockNumber: tx.blockNumber.toString(),
        timestamp: tx.timestamp,
        fromLabel: tx.fromLabel,
        toLabel: tx.toLabel
      }));
    } catch (error) {
      logger.error('Failed to get recent transactions by address:', error);
      throw error;
    }
  }

  // ===== Address Label Operations =====

  public async saveAddressLabel(label: AddressLabel): Promise<void> {
    try {
      await this.prisma.addressLabel.upsert({
        where: {
          address_chain: {
            address: label.address.toLowerCase(),
            chain: label.chain
          }
        },
        update: {
          label: label.label,
          type: label.type
        },
        create: {
          address: label.address.toLowerCase(),
          label: label.label,
          type: label.type,
          chain: label.chain
        }
      });
    } catch (error) {
      logger.error('Failed to save address label:', error);
      throw error;
    }
  }

  public async getAddressLabels(address: string, chain?: ChainType): Promise<AddressLabel[]> {
    try {
      const labels = await this.prisma.addressLabel.findMany({
        where: {
          address: address.toLowerCase(),
          ...(chain && { chain })
        }
      });

      return labels.map(label => ({
        id: label.id.toString(),
        address: label.address,
        label: label.label,
        type: label.type,
        chain: label.chain as ChainType,
        createdAt: label.createdAt
      }));
    } catch (error) {
      logger.error('Failed to get address labels:', error);
      throw error;
    }
  }

  // ===== Analysis Operations =====

  // Entity operations
  public async createEntity(entity: any): Promise<string> {
    try {
      const result = await this.prisma.entity.create({
        data: {
          entityId: entity.id,
          name: entity.name,
          type: entity.type,
          riskScore: entity.riskScore,
          confidence: entity.confidence,
          metadata: entity.metadata || {}
        }
      });
      return result.entityId;
    } catch (error) {
      logger.error('Failed to create entity:', error);
      throw error;
    }
  }

  public async getEntityById(entityId: string): Promise<any | null> {
    try {
      const entity = await this.prisma.entity.findUnique({
        where: { entityId },
        include: {
          addresses: true,
          addressProfiles: true
        }
      });

      if (!entity) return null;

      return {
        id: entity.entityId,
        name: entity.name,
        type: entity.type,
        riskScore: entity.riskScore,
        confidence: parseFloat(entity.confidence.toString()),
        metadata: entity.metadata,
        lastUpdated: entity.updatedAt,
        addresses: entity.addresses.map(addr => addr.address),
        chains: [...new Set(entity.addresses.map(addr => addr.chain))]
      };
    } catch (error) {
      logger.error('Failed to get entity by ID:', error);
      throw error;
    }
  }

  public async updateEntity(entityId: string, updates: any): Promise<void> {
    try {
      await this.prisma.entity.update({
        where: { entityId },
        data: {
          name: updates.name,
          type: updates.type,
          riskScore: updates.riskScore,
          confidence: updates.confidence,
          metadata: updates.metadata || {}
        }
      });
    } catch (error) {
      logger.error('Failed to update entity:', error);
      throw error;
    }
  }

  // Address Profile operations
  public async createOrUpdateAddressProfile(profile: any): Promise<void> {
    try {
      await this.prisma.addressProfile.upsert({
        where: {
          address_chain: {
            address: profile.address.toLowerCase(),
            chain: profile.chain
          }
        },
        update: {
          entityId: profile.entityId,
          riskScore: profile.riskScore,
          totalTransactions: profile.totalTransactions,
          totalVolumeUsd: profile.totalVolumeUsd,
          lastActive: profile.lastActive,
          activityScore: profile.activityScore,
          metadata: profile.metadata || {}
        },
        create: {
          address: profile.address.toLowerCase(),
          chain: profile.chain,
          entityId: profile.entityId,
          riskScore: profile.riskScore,
          totalTransactions: profile.totalTransactions,
          totalVolumeUsd: profile.totalVolumeUsd,
          firstSeen: profile.firstSeen,
          lastActive: profile.lastActive,
          activityScore: profile.activityScore,
          metadata: profile.metadata || {}
        }
      });
    } catch (error) {
      logger.error('Failed to create/update address profile:', error);
      throw error;
    }
  }

  public async getAddressProfile(address: string, chain: ChainType): Promise<any | null> {
    try {
      const profile = await this.prisma.addressProfile.findUnique({
        where: {
          address_chain: {
            address: address.toLowerCase(),
            chain
          }
        },
        include: {
          entity: true,
          transactionPatterns: true,
          behaviorInsights: true,
          anomalyAlerts: {
            where: { status: 'active' }
          }
        }
      });

      if (!profile) return null;

      return {
        address: profile.address,
        chain: profile.chain,
        entityId: profile.entityId,
        riskScore: profile.riskScore,
        totalTransactions: profile.totalTransactions,
        totalVolumeUsd: parseFloat(profile.totalVolumeUsd.toString()),
        firstSeen: profile.firstSeen,
        lastActive: profile.lastActive,
        activityScore: parseFloat(profile.activityScore.toString()),
        metadata: profile.metadata,
        entity: profile.entity,
        patterns: profile.transactionPatterns,
        insights: profile.behaviorInsights,
        alerts: profile.anomalyAlerts
      };
    } catch (error) {
      logger.error('Failed to get address profile:', error);
      throw error;
    }
  }

  // Transaction Pattern operations
  public async saveTransactionPattern(pattern: any): Promise<void> {
    try {
      await this.prisma.transactionPattern.upsert({
        where: { patternId: pattern.id },
        update: {
          confidence: pattern.confidence,
          description: pattern.description,
          frequency: pattern.frequency,
          avgAmountUsd: pattern.avgAmount,
          metadata: pattern.metadata || {}
        },
        create: {
          patternId: pattern.id,
          address: pattern.address.toLowerCase(),
          chain: pattern.chain,
          patternType: pattern.type,
          confidence: pattern.confidence,
          description: pattern.description,
          frequency: pattern.frequency,
          avgAmountUsd: pattern.avgAmount,
          metadata: pattern.metadata || {}
        }
      });
    } catch (error) {
      logger.error('Failed to save transaction pattern:', error);
      throw error;
    }
  }

  public async getTransactionPatterns(address: string, chain: ChainType): Promise<any[]> {
    try {
      const patterns = await this.prisma.transactionPattern.findMany({
        where: {
          address: address.toLowerCase(),
          chain
        },
        orderBy: { detectedAt: 'desc' }
      });

      return patterns.map(pattern => ({
        id: pattern.patternId,
        type: pattern.patternType,
        confidence: parseFloat(pattern.confidence.toString()),
        description: pattern.description,
        frequency: pattern.frequency,
        avgAmount: pattern.avgAmountUsd ? parseFloat(pattern.avgAmountUsd.toString()) : null,
        detectedAt: pattern.detectedAt,
        lastSeen: pattern.lastSeen,
        metadata: pattern.metadata
      }));
    } catch (error) {
      logger.error('Failed to get transaction patterns:', error);
      throw error;
    }
  }

  // Behavior Insight operations
  public async saveBehaviorInsight(insight: any): Promise<void> {
    try {
      await this.prisma.behaviorInsight.upsert({
        where: { insightId: insight.id },
        update: {
          title: insight.title,
          description: insight.description,
          severity: insight.severity,
          confidence: insight.confidence,
          metadata: insight.metadata || {}
        },
        create: {
          insightId: insight.id,
          address: insight.address.toLowerCase(),
          type: insight.type,
          title: insight.title,
          description: insight.description,
          severity: insight.severity,
          confidence: insight.confidence,
          metadata: insight.metadata || {}
        }
      });
    } catch (error) {
      logger.error('Failed to save behavior insight:', error);
      throw error;
    }
  }

  public async getBehaviorInsights(address: string): Promise<any[]> {
    try {
      const insights = await this.prisma.behaviorInsight.findMany({
        where: { address: address.toLowerCase() },
        orderBy: { createdAt: 'desc' }
      });

      return insights.map(insight => ({
        id: insight.insightId,
        address: insight.address,
        type: insight.type,
        title: insight.title,
        description: insight.description,
        severity: insight.severity,
        confidence: parseFloat(insight.confidence.toString()),
        timestamp: insight.createdAt,
        metadata: insight.metadata
      }));
    } catch (error) {
      logger.error('Failed to get behavior insights:', error);
      throw error;
    }
  }

  // Anomaly Alert operations
  public async saveAnomalyAlert(alert: any): Promise<void> {
    try {
      await this.prisma.anomalyAlert.upsert({
        where: { alertId: alert.id },
        update: {
          severity: alert.severity,
          title: alert.title,
          description: alert.description,
          status: alert.status || 'active',
          metadata: alert.metadata || {}
        },
        create: {
          alertId: alert.id,
          address: alert.address.toLowerCase(),
          chain: alert.chain,
          anomalyType: alert.type,
          severity: alert.severity,
          title: alert.title,
          description: alert.description,
          thresholdValue: alert.threshold,
          actualValue: alert.actualValue,
          confidence: alert.confidence,
          status: alert.status || 'active',
          metadata: alert.metadata || {}
        }
      });
    } catch (error) {
      logger.error('Failed to save anomaly alert:', error);
      throw error;
    }
  }

  public async getAnomalyAlerts(address?: string, chain?: ChainType, status?: string): Promise<any[]> {
    try {
      const where: any = {};

      if (address) {
        where.address = address.toLowerCase();
      }

      if (chain) {
        where.chain = chain;
      }

      if (status) {
        where.status = status;
      }

      const alerts = await this.prisma.anomalyAlert.findMany({
        where,
        orderBy: { detectedAt: 'desc' }
      });

      return alerts.map(alert => ({
        id: alert.alertId,
        address: alert.address,
        chain: alert.chain,
        type: alert.anomalyType,
        severity: alert.severity,
        title: alert.title,
        description: alert.description,
        threshold: alert.thresholdValue ? parseFloat(alert.thresholdValue.toString()) : null,
        actualValue: alert.actualValue ? parseFloat(alert.actualValue.toString()) : null,
        confidence: parseFloat(alert.confidence.toString()),
        status: alert.status,
        detectedAt: alert.detectedAt,
        resolvedAt: alert.resolvedAt,
        metadata: alert.metadata
      }));
    } catch (error) {
      logger.error('Failed to get anomaly alerts:', error);
      throw error;
    }
  }

  // Market Impact Analysis operations
  public async saveMarketImpactAnalysis(analysis: any): Promise<void> {
    try {
      await this.prisma.marketImpactAnalysis.upsert({
        where: { transactionHash: analysis.transactionHash },
        update: {
          impactScore: analysis.impactScore,
          liquidityImpact: analysis.liquidityImpact,
          priceImpactPercentage: analysis.priceImpactPercentage,
          volumeImpact: analysis.volumeImpact,
          marketSentiment: analysis.marketSentiment,
          analysisMetadata: analysis.metadata || {}
        },
        create: {
          transactionHash: analysis.transactionHash,
          impactScore: analysis.impactScore,
          liquidityImpact: analysis.liquidityImpact,
          priceImpactPercentage: analysis.priceImpactPercentage,
          volumeImpact: analysis.volumeImpact,
          marketSentiment: analysis.marketSentiment,
          analysisMetadata: analysis.metadata || {}
        }
      });
    } catch (error) {
      logger.error('Failed to save market impact analysis:', error);
      throw error;
    }
  }

  public async getMarketImpactAnalysis(transactionHash: string): Promise<any | null> {
    try {
      const analysis = await this.prisma.marketImpactAnalysis.findUnique({
        where: { transactionHash },
        include: { transaction: true }
      });

      if (!analysis) return null;

      return {
        transactionHash: analysis.transactionHash,
        impactScore: parseFloat(analysis.impactScore.toString()),
        liquidityImpact: analysis.liquidityImpact ? parseFloat(analysis.liquidityImpact.toString()) : null,
        priceImpactPercentage: analysis.priceImpactPercentage ? parseFloat(analysis.priceImpactPercentage.toString()) : null,
        volumeImpact: analysis.volumeImpact ? parseFloat(analysis.volumeImpact.toString()) : null,
        marketSentiment: analysis.marketSentiment,
        analyzedAt: analysis.analyzedAt,
        metadata: analysis.analysisMetadata,
        transaction: analysis.transaction
      };
    } catch (error) {
      logger.error('Failed to get market impact analysis:', error);
      throw error;
    }
  }

  // Intelligence Report operations
  public async saveIntelligenceReport(report: any): Promise<void> {
    try {
      await this.prisma.intelligenceReport.upsert({
        where: { reportId: report.id },
        update: {
          title: report.title,
          summary: report.summary,
          content: report.content,
          priority: report.priority,
          tags: report.tags,
          entities: report.entities,
          addresses: report.addresses,
          chains: report.chains,
          metadata: report.metadata || {}
        },
        create: {
          reportId: report.id,
          title: report.title,
          summary: report.summary,
          content: report.content,
          reportType: report.type,
          priority: report.priority,
          tags: report.tags,
          entities: report.entities,
          addresses: report.addresses,
          chains: report.chains,
          metadata: report.metadata || {},
          expiresAt: report.expiresAt
        }
      });
    } catch (error) {
      logger.error('Failed to save intelligence report:', error);
      throw error;
    }
  }

  public async getIntelligenceReports(type?: string, priority?: string, limit: number = 50): Promise<any[]> {
    try {
      const where: any = {};

      if (type) {
        where.reportType = type;
      }

      if (priority) {
        where.priority = priority;
      }

      const reports = await this.prisma.intelligenceReport.findMany({
        where,
        orderBy: { generatedAt: 'desc' },
        take: limit
      });

      return reports.map(report => ({
        id: report.reportId,
        title: report.title,
        summary: report.summary,
        content: report.content,
        type: report.reportType,
        priority: report.priority,
        tags: report.tags,
        entities: report.entities,
        addresses: report.addresses,
        chains: report.chains,
        generatedAt: report.generatedAt,
        expiresAt: report.expiresAt,
        metadata: report.metadata
      }));
    } catch (error) {
      logger.error('Failed to get intelligence reports:', error);
      throw error;
    }
  }

  // Pattern Detection Cache operations
  public async getCachedPattern(cacheKey: string): Promise<any | null> {
    try {
      const cache = await this.prisma.patternDetectionCache.findFirst({
        where: {
          cacheKey,
          expiresAt: { gt: new Date() }
        }
      });

      return cache?.patternData || null;
    } catch (error) {
      logger.error('Failed to get cached pattern:', error);
      throw error;
    }
  }

  public async setCachedPattern(cacheKey: string, address: string, chain: ChainType, data: any, ttlMinutes: number = 60): Promise<void> {
    try {
      const expiresAt = new Date(Date.now() + ttlMinutes * 60 * 1000);
      
      await this.prisma.patternDetectionCache.upsert({
        where: { cacheKey },
        update: {
          patternData: data,
          expiresAt
        },
        create: {
          cacheKey,
          address: address.toLowerCase(),
          chain,
          patternData: data,
          expiresAt
        }
      });
    } catch (error) {
      logger.error('Failed to set cached pattern:', error);
      throw error;
    }
  }

  // Clean up expired cache entries
  public async cleanupExpiredCache(): Promise<void> {
    try {
      await this.prisma.patternDetectionCache.deleteMany({
        where: {
          expiresAt: { lt: new Date() }
        }
      });
    } catch (error) {
      logger.error('Failed to cleanup expired cache:', error);
      throw error;
    }
  }

  // Get Prisma client for advanced operations
  public getClient(): PrismaClient {
    return this.prisma;
  }
} 